/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pbb_template_updater;

import java.io.*;
import java.net.*;
import java.util.*;

/**
 *
 * @author Jon Huss
 */
public class PbbGNFDataGetter {
    
    public static final String tempFile = "PBB_temp_19553ea33959fbb.tmp";
    //old location...
    //public static final String geneReportUrl = "http://biogps.gnf.org/services/GeneReport.aspx?gene_id=";
    
    //new Location...
    public static final String geneReportUrl = "http://api.biogps.gnf.org/Genes/GetGenericReport.aspx?templateId=0&gene_id=";
    private String rootDirectory;
    
    /** Creates a new instance of PBBxmlGetter */
    public PbbGNFDataGetter(String rootDir) {
        rootDirectory = rootDir;
    }
    
    public String getXmlFilename(){
        return this.rootDirectory + tempFile;
    }
    
    //http://biogps.gnf.org/services/GeneReport.aspx?gene_id=id1+id2+id3
    
    public String getXmlData(String[] ids) {
        if (ids.length < 1) {
            System.out.println("Error: No GeneIDs found.");
            return null;
        }
        String page = geneReportUrl + ids[0];
        for (int i = 1; i < ids.length; i++){
            page +="+" + ids[i];
        }
        
        //it has become necessary to output our file and download at the same time..
        String filename = this.rootDirectory + this.tempFile;
        boolean xmlResult = downloadXmlPage(page, filename);
        if (xmlResult == false) {
            return null;
        }

//        //if we get here, everything worked great.
        return filename;
        
    }
    
    private static final void dumpDataToFile(String fileName, String data) throws IOException {
        File out;
        out = new File(fileName);
        if (out.exists()){
            out.delete();
        }
        File parent = new File(out.getParent());
        if (parent != null){
            parent.mkdirs();
        }
        out.createNewFile();
        if (out.canWrite()){
            FileWriter fw = new FileWriter(out);
            fw.write(data);
        }
        
    }
    
    
    public boolean downloadXmlPage(String page, String fileName){
        //wraps for error catching.
        boolean clear = false;
        int tries = 0;
        while (!clear){
            
            try {
                System.out.println("Downloading xml data...");
                File out;
                out = new File(fileName);
                if (out.exists()){
                    out.delete();
                }
                File parent = new File(out.getParent());
                if (parent != null){
                    parent.mkdirs();
                }
                out.createNewFile();
                if (out.canWrite()){
                    
                    
                    boolean data = downloadXmlPageH(page,out);
                    return data;
                }
            } catch(Exception e) {
                System.out.println("Entrez: Encountered Error while Downloading:");
                System.out.println(e.getMessage());
                if (tries < 3){
                    System.out.println("Trying "+ (3 - tries) + " more time(s) in 10 seconds...");
                    this.updateWait(10000);
                    this.allowComm();
                    tries++;
                    continue;
                    
                } else {
                    System.out.println("3 tries failed; Requiring User Input:");
                    tries = 0;
                }
                try {
                    BufferedReader inputLine = new BufferedReader(new InputStreamReader(System.in));
                    System.out.println("Try Again? (y/n)");
                    System.out.flush();
                    String input = inputLine.readLine();
                    //input = "y";
                    if (input.compareToIgnoreCase("y") == 0){
                        clear= false;
                    }else {
                        clear = true;
                        //throw new PBBWikiException("User Aborted Download due to error.",e);
                        return false;
                    }
                    
                } catch (IOException ex) {
                    return false;
                    //throw new PBBWikiException("Unrecoverable IO Error.",ex);
                    //System.out.println("Unrecoverable IO Error.");
                    //ex.printStackTrace();
                    //System.exit(1);
                }
            }
            
        }
        //throw new PBBWikiException("Unknown Download Error.");
        return false;
    }
    
    //Helper method for downloadPdbImage
    //return true iff it has downloaded more than 200 characters.
    private boolean downloadXmlPageH(String page, File out) throws Exception{
        //Returns the data of the indicated page. It is found in the wpTextbox1 area.
        String lineSep = System.getProperty("line.separator");
        //page = encode(page);
        URL xmlURL;
        URLConnection xmlConn;
        
        xmlURL = new URL(page);
        //glblLog.addEntry("SYSTEM","ENTREZCOMM","Downloading File:"+ entURL.toString(),PBBLogging.logs.SY);
        
        xmlConn = xmlURL.openConnection();
        //editConn.setRequestProperty("Cookie", this.getCookieData());
        //editConn.getContent();
        xmlConn.getContent();
        String input = "";
        BufferedReader xmlBR = new BufferedReader(new InputStreamReader(xmlConn.getInputStream(),"UTF-8"));
        
        //BufferedWriter bw = new BufferedWriter(new FileWriter(destination));
        String inLine = "";
        FileWriter fw = new FileWriter(out);
        //fw.write(data);
        int tmpint = xmlConn.getContentLength();
        if (tmpint > 0) {
            System.out.println("Downloading approximately " + tmpint + " characters of data.");
            System.out.flush();
        }
        
        double tmpCount = 0;
        boolean result = false;
        while ( (inLine = xmlBR.readLine()) != null) {
            if (inLine.indexOf("<?xml") != -1){
                //need to skip the encoding line
                continue;
            }
            input += inLine + lineSep;
            tmpCount = tmpCount + inLine.length();
            if (input.length() > 200){
                result = true;
                fw.write(input);
                input = "";
            }
            
        }
        System.out.println("Downloaded " + tmpCount + " Characters.");
        if (input.length() > 0) {
            fw.write(input);
        }
        fw.flush();
        fw.close();
        return result;
        
    }
    private Date nextComm;
    private void updateWait(int wait){
        Date now = new Date();
        nextComm = new Date(now.getTime() + wait);
        //DEBUG
        //System.out.println("NextComm = " + nextComm.getTime());
        //System.out.println("Now = " + now.getTime());
        //System.out.println("Difference = " + (nextComm.getTime() - now.getTime())+ " should be ~" + wait);
        
        
        
    }
    private void allowComm() {
        //this function makes the bot wait until it is allowed to perform the next communication with Wiki.
        Date now = new Date();
        
        long wait = nextComm.getTime() - now.getTime();
        //System.out.println("Wait = " + wait);
        double waitTime = ((double)wait)/1000;
        if (wait > 0) {
            System.out.println("Waiting " + waitTime + " seconds for server cooldown.");
            System.out.flush();
            long left = wait;
            while( left > 10){
                System.out.print(".");
                System.out.print(" ");
                System.out.flush();
                try {
                    if( left > 1000){
                        Thread.currentThread().sleep(1000);
                        left = left - 1000;
                    }else {
                        Thread.currentThread().sleep(left);
                        left = 0;
                        
                    }
                } catch (InterruptedException ex) {
                    System.out.println("Interrupted While Sleeping. Non-hazardous Error (ignored).");
                    //ex.printStackTrace();
                }
                
                
            }
            Date time2 = new Date();
            long actWait = time2.getTime() - now.getTime();
            System.out.println(" ("+ actWait + " milliseconds.)");
            //log.addEntry("SYSTEM","SLEPT","Waited " + actWait + " milliseconds for Server Cooldown.",PBBLogging.logs.SY);
            
        }
        return;
        
    }
    
}
